package org.humboldt.cassia.zk.actions;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.humboldt.cassia.componentes.adjuntos.FacadeAdjuntos;
import org.humboldt.cassia.core.Constantes;
import org.humboldt.cassia.core.jdo.AtributosPerfil;
import org.humboldt.cassia.core.jdo.Decomiso;
import org.humboldt.cassia.core.jdo.Homologacion;
import org.humboldt.cassia.core.jdo.InformacionDecomiso;
import org.humboldt.cassia.core.jdo.PerfilDocumentacion;
import org.humboldt.cassia.core.utils.ConstantesUtil;
import org.humboldt.cassia.core.utils.XsdTypes;
import org.humboldt.cassia.zk.model.ArbolPerfilModel;
import org.humboldt.cassia.zk.render.ArbolPerfilDecomisoRender;
import org.humboldt.cassia.zk.render.BusquedaDecomisosGridRenderer;
import org.humboldt.cassia.zk.util.SessionUtil;
import org.humboldt.cassia.zk.util.ZKUtil;
import org.humboldt.cassia.zk.vo.TreeAtributoPerfil;
import org.humboldt.cassia.zk.vo.TreePerfil;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zul.Button;
import org.zkoss.zul.Column;
import org.zkoss.zul.Columns;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Filedownload;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Intbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.Radio;
import org.zkoss.zul.Radiogroup;
import org.zkoss.zul.Row;
import org.zkoss.zul.Rows;
import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Window;

public class DecomisosAction {

	public void nuevoDecomiso(Component componente, String strconjunto) {
		Window win = (Window) Executions.createComponents("/decomisos/nuevo.zul", null, null);
		try {
			// Se crea el decomiso
			long idDecomiso = SessionUtil.getFacadeDecomisosCore().crearDecomiso(Long.parseLong(strconjunto), SessionUtil.getUsuario(componente.getDesktop().getSession()));
			PerfilDocumentacion perfil = SessionUtil.getFacadeConsultasPerfilesCassiaCore().consultarPerfilbyNombre("Perfil Decomisos");
			TreePerfil treePerfil = new TreePerfil(perfil);
			Decomiso decomiso = SessionUtil.getFacadeDecomisosCore().consultarDecomiso(idDecomiso);
			TreeAtributoPerfil padre = new TreeAtributoPerfil(null, null);
			ubicarValoresEnPerfil(padre, new ArrayList<TreeAtributoPerfil>(treePerfil.getTreeAtributos()), decomiso.getInformacionDecomiso());
			if (treePerfil.getTreeAtributos() != null)
				treePerfil.setTreeAtributos(padre.getTreeHijos());
			ArbolPerfilModel model = new ArbolPerfilModel(treePerfil);
			model.setPerfil(treePerfil);
			((Tree) win.getFellow("treePerfil")).setModel(model);

			ArbolPerfilDecomisoRender renderer = new ArbolPerfilDecomisoRender();
			Tree arbol = (Tree) win.getFellow("treePerfil");
			arbol.setTreeitemRenderer(renderer);
			((Button) win.getFellow("btn_guardar_decomiso")).setAttribute("decomiso", decomiso);
			((Button) win.getFellow("btn_guardar_decomiso")).setAttribute("btnnuevo", componente);
			((Button) win.getFellow("btn_cancelar_decomiso")).setAttribute("decomiso", decomiso);
			((Button) win.getFellow("btn_cancelar_decomiso")).setAttribute("origen", componente);
			ListModel mdlDecomisos = new org.humboldt.cassia.zk.model.DecomisosModel().getGridModel(Long.parseLong(strconjunto));
			((Grid) componente.getRoot().getFellow("gridDecomisosEspecie")).setModel(mdlDecomisos);
			win.doModal();
		} catch (InterruptedException e) {
		}
	}

	public void editarDecomiso(Decomiso decomiso) {
		Window win = (Window) Executions.createComponents("/decomisos/editar.zul", null, null);
		long idDecomiso = decomiso.getId();
		PerfilDocumentacion perfil = SessionUtil.getFacadeConsultasPerfilesCassiaCore().consultarPerfilbyNombre("Perfil Decomisos");
		TreePerfil treePerfil = new TreePerfil(perfil);
		decomiso = SessionUtil.getFacadeDecomisosCore().consultarDecomiso(idDecomiso);
		TreeAtributoPerfil padre = new TreeAtributoPerfil(null, null);
		ubicarValoresEnPerfil(padre, new ArrayList<TreeAtributoPerfil>(treePerfil.getTreeAtributos()), decomiso.getInformacionDecomiso());
		if (treePerfil.getTreeAtributos() != null)
			treePerfil.setTreeAtributos(padre.getTreeHijos());
		ArbolPerfilModel model = new ArbolPerfilModel(treePerfil);
		model.setPerfil(treePerfil);
		((Tree) win.getFellow("treePerfil")).setModel(model);

		ArbolPerfilDecomisoRender renderer = new ArbolPerfilDecomisoRender();
		Tree arbol = (Tree) win.getFellow("treePerfil");
		arbol.setTreeitemRenderer(renderer);
		((Button) win.getFellow("btn_guardar_decomiso")).setAttribute("decomiso", decomiso);
		try {
			win.doModal();
		} catch (Exception e) {
		}
	}

	public void verDecomiso(Decomiso decomiso) {
		Window win = (Window) Executions.createComponents("/decomisos/ver.zul", null, null);
		long idDecomiso = decomiso.getId();
		PerfilDocumentacion perfil = SessionUtil.getFacadeConsultasPerfilesCassiaCore().consultarPerfilbyNombre("Perfil Decomisos");
		TreePerfil treePerfil = new TreePerfil(perfil);
		decomiso = SessionUtil.getFacadeDecomisosCore().consultarDecomiso(idDecomiso);
		TreeAtributoPerfil padre = new TreeAtributoPerfil(null, null);
		ubicarValoresEnPerfil(padre, new ArrayList<TreeAtributoPerfil>(treePerfil.getTreeAtributos()), decomiso.getInformacionDecomiso());
		if (treePerfil.getTreeAtributos() != null)
			treePerfil.setTreeAtributos(padre.getTreeHijos());
		ArbolPerfilModel model = new ArbolPerfilModel(treePerfil);
		model.setPerfil(treePerfil);
		((Tree) win.getFellow("treePerfil")).setModel(model);

		ArbolPerfilDecomisoRender renderer = new ArbolPerfilDecomisoRender();
		renderer.setEditar(false);
		Tree arbol = (Tree) win.getFellow("treePerfil");
		arbol.setTreeitemRenderer(renderer);
		try {
			win.doModal();
		} catch (Exception e) {
		}
	}

	public void guardarInformacionDecomiso(Component componente) {
		Decomiso decomiso = (Decomiso) componente.getAttribute("decomiso");
		ArbolPerfilModel model = (ArbolPerfilModel) ((Tree) componente.getRoot().getFellow("treePerfil")).getModel();
		ArrayList<InformacionDecomiso> valoresAtributo = new ArrayList<InformacionDecomiso>();
		for (TreeAtributoPerfil treeAtributoPerfil : model.getPerfil().getTreeAtributos()) {
			InformacionDecomiso valor = treeAtributoPerfil.getNewInformacionDecomiso();
			obtenerValores(treeAtributoPerfil, valor);
			valoresAtributo.add(valor);
		}
		SessionUtil.getFacadeDecomisosCore().guardarInformacionDecomiso(decomiso, valoresAtributo);
		ListModel mdlDecomisos = new org.humboldt.cassia.zk.model.DecomisosModel().getGridModel(decomiso.getConjunto().getId());
		if (componente.getAttribute("btnnuevo") != null) {
			((Grid) ((Component) componente.getAttribute("btnnuevo")).getRoot().getFellow("gridDecomisosEspecie")).setModel(mdlDecomisos);
		}
	}

	private void obtenerValores(TreeAtributoPerfil atributoPerfil, InformacionDecomiso padre) {
		if (atributoPerfil.getTreeHijos() == null) {
			return;
		}
		for (TreeAtributoPerfil treeAtributoPerfil : atributoPerfil.getTreeHijos()) {
			if (padre.getHijos() == null) {
				padre.setHijos(new ArrayList<InformacionDecomiso>());
			}
			InformacionDecomiso valor = treeAtributoPerfil.getNewInformacionDecomiso();
			InformacionDecomiso valorAnterior = treeAtributoPerfil.getInformacionDecomiso();
			if (treeAtributoPerfil.getComponenteExterno() != null) {
				FacadeAdjuntos facadeAdjuntos = new FacadeAdjuntos();
				facadeAdjuntos.setFactory(SessionUtil.getPersistenceManager());
				valor.setAdjuntos(facadeAdjuntos.consultarAdjuntosDecomisos(valorAnterior.getId()));
				System.out.println("Obteniendo adjuntos para " + valorAnterior.getId() + " " + valor.getAdjuntos());
			}
			obtenerValores(treeAtributoPerfil, valor);
			padre.getHijos().add(valor);
		}
	}

	private void ubicarValoresEnPerfil(TreeAtributoPerfil padre, ArrayList<TreeAtributoPerfil> atributosPerfil, Collection<InformacionDecomiso> valores) {
		if (atributosPerfil == null) {
			return;
		}
		ArrayList<TreeAtributoPerfil> lstAtributosPerfil = new ArrayList<TreeAtributoPerfil>();
		for (int j = 0; j < atributosPerfil.size(); j++) {
			ArrayList<InformacionDecomiso> valorAtributos = new ArrayList<InformacionDecomiso>();
			buscarAtributos(valores, (TreeAtributoPerfil) atributosPerfil.get(j), valorAtributos);
			if (valorAtributos.size() == 0) {
				TreeAtributoPerfil atributo = (TreeAtributoPerfil) atributosPerfil.get(j);
				InformacionDecomiso valor = new InformacionDecomiso();
				valor.setAtributo(atributo.getId());
				valor.setNombreAtributo(atributo.getNombre());
				valor.setValor("");
				atributo.setInformacionDecomiso(valor);
				lstAtributosPerfil.add(atributo);
			} else {
				for (int i = 0; i < valorAtributos.size(); i++) {
					TreeAtributoPerfil atributoHijo = new TreeAtributoPerfil((TreeAtributoPerfil) atributosPerfil.get(j), padre);
					if (valorAtributos.size() == 1 && (padre == null || padre.getValor() == null || padre.getValor().getId() == null)) {
						atributoHijo.setInformacionDecomiso(valorAtributos.get(i));
						lstAtributosPerfil.add(atributoHijo);
					} else {
						if (valorAtributos != null && valorAtributos.get(i) != null && valorAtributos.get(i).getPadre() != null && padre != null && padre.getValor() != null && padre.getValor().getId() != null && valorAtributos.get(i).getPadre().longValue() == padre.getValor().getId().longValue()) {
							atributoHijo.setInformacionDecomiso(valorAtributos.get(i));
							lstAtributosPerfil.add(atributoHijo);
						}
					}
				}
			}
		}
		if (padre != null) {
			padre.setTreeHijos(lstAtributosPerfil);
		}
		for (int j = 0; j < lstAtributosPerfil.size(); j++) {
			TreeAtributoPerfil atributo = (TreeAtributoPerfil) lstAtributosPerfil.get(j);
			if (atributo.getTreeHijos() != null) {
				ubicarValoresEnPerfil(atributo, new ArrayList<TreeAtributoPerfil>(atributo.getTreeHijos()), valores);
			}
		}
	}

	private void buscarAtributos(Collection<InformacionDecomiso> valores, TreeAtributoPerfil atributo, ArrayList<InformacionDecomiso> valorAtributos) {
		if (valores == null) {
			return;
		}
		for (InformacionDecomiso valorAtributo : valores) {
			if (atributo.getId().longValue() == valorAtributo.getAtributo().longValue()) {
				valorAtributos.add(valorAtributo);
			}
			buscarAtributos(valorAtributo.getHijos(), atributo, valorAtributos);
		}
	}

	public void cancelarNuevoDecomiso(Component componente) {
		Decomiso decomiso = (Decomiso) componente.getAttribute("decomiso");
		SessionUtil.getFacadeDecomisosCore().eliminarDecomiso(decomiso);
		ListModel mdlDecomisos = new org.humboldt.cassia.zk.model.DecomisosModel().getGridModel(decomiso.getConjunto().getId());
		((Grid) ((Component) componente.getAttribute("origen")).getRoot().getFellow("gridDecomisosEspecie")).setModel(mdlDecomisos);
	}

	public void buscarDecomisos(Component componente, Grid gridParametros) {
		componente.getRoot().getFellow("tab_resultado").setVisible(true);
		Rows rows = gridParametros.getRows();
		if (rows != null) {
			List rowChild = rows.getChildren();
			HashMap<Long, Long> decomisosBuscadosOr = new HashMap<Long, Long>();
			HashMap<Long, Integer> decomisosBuscadosAnd = new HashMap<Long, Integer>();
			int qAnd = 0;
			for (Iterator itRowChild = rowChild.iterator(); itRowChild.hasNext();) {
				Object objRow = (Object) itRowChild.next();
				if (objRow instanceof Row) {
					Row row = (Row) objRow;
					if (row.getAttribute("atributo") != null) {
						AtributosPerfil atributoPerfil = (AtributosPerfil) row.getAttribute("atributo");
						boolean and = false;
						if (((Radio) row.getFellow("rdBusAtributo_Y_" + atributoPerfil.getId())).isChecked()) {
							and = true;
						}
						if (XsdTypes.XSD_INTEGER.equals(atributoPerfil.getTipo())) {
							Intbox txtAtributoIni = ((Intbox) row.getFellow("txtAtributo_" + atributoPerfil.getId() + "_Ini"));
							Intbox txtAtributoFin = ((Intbox) row.getFellow("txtAtributo_" + atributoPerfil.getId() + "_Fin"));
							Integer valorIni = txtAtributoIni.getValue();
							Integer valorFin = txtAtributoFin.getValue();
							if (valorIni != null || valorFin != null && and)
								qAnd ++;
							Collection<Long> decomisos = SessionUtil.getFacadeDecomisosCore().consultarDecomisosbyInformacion(atributoPerfil, valorIni, valorFin);
							for (Long idDecomiso : decomisos) {
								if (and) {
									if (decomisosBuscadosAnd.get(idDecomiso) == null)
										decomisosBuscadosAnd.put(idDecomiso, new Integer(0));
									decomisosBuscadosAnd.put(idDecomiso, new Integer(decomisosBuscadosAnd.get(idDecomiso).intValue() + 1));
								} else
									decomisosBuscadosOr.put(idDecomiso, idDecomiso);
							}
						} else if (XsdTypes.XSD_DATE.equals(atributoPerfil.getTipo())) {
							Datebox txtAtributoIni = ((Datebox) row.getFellow("txtAtributo_" + atributoPerfil.getId() + "_Ini"));
							Datebox txtAtributoFin = ((Datebox) row.getFellow("txtAtributo_" + atributoPerfil.getId() + "_Fin"));
							Date valorIni = txtAtributoIni.getValue();
							Date valorFin = txtAtributoFin.getValue();
							if (valorIni != null || valorFin != null && and)
								qAnd ++;
							Collection<Long> decomisos = SessionUtil.getFacadeDecomisosCore().consultarDecomisosbyInformacion(atributoPerfil, valorIni, valorFin);
							for (Long idDecomiso : decomisos) {
								if (and) {
									if (decomisosBuscadosAnd.get(idDecomiso) == null)
										decomisosBuscadosAnd.put(idDecomiso, new Integer(0));
									decomisosBuscadosAnd.put(idDecomiso, new Integer(decomisosBuscadosAnd.get(idDecomiso).intValue() + 1));
								} else
									decomisosBuscadosOr.put(idDecomiso, idDecomiso);
							}
						} else {
							Textbox txtAtributo = ((Textbox) row.getFellow("txtBusAtributo_" + atributoPerfil.getId()));
							if (txtAtributo.getValue() != null && txtAtributo.getValue().trim().length() > 0) {
								Collection<Long> decomisos = SessionUtil.getFacadeDecomisosCore().consultarDecomisosbyInformacion(atributoPerfil, txtAtributo.getValue(), null);
								if (and)
									qAnd++;
								for (Long idDecomiso : decomisos) {
									if (and) {
										if (decomisosBuscadosAnd.get(idDecomiso) == null)
											decomisosBuscadosAnd.put(idDecomiso, new Integer(0));
										decomisosBuscadosAnd.put(idDecomiso, new Integer(decomisosBuscadosAnd.get(idDecomiso).intValue() + 1));
									} else
										decomisosBuscadosOr.put(idDecomiso, idDecomiso);
								}
							}
						}
					}
				}
			}
			ArrayList<Decomiso> resultadoDecomisos = new ArrayList<Decomiso>();
			for (Long idDecomiso : decomisosBuscadosAnd.keySet()) {
				if (decomisosBuscadosAnd.get(idDecomiso).intValue() == qAnd)
					decomisosBuscadosOr.put(idDecomiso, idDecomiso);
			}
			for (Long idDecomiso : decomisosBuscadosOr.values()) {
				resultadoDecomisos.add(SessionUtil.getFacadeDecomisosCore().consultarDecomiso(idDecomiso));
			}
			SimpleListModel mdlResultado= new SimpleListModel(resultadoDecomisos);
			Grid grdResultado = (Grid)componente.getRoot().getFellow("gridResultadoBusqueda");
			BusquedaDecomisosGridRenderer renderer = new BusquedaDecomisosGridRenderer();
			renderer.setPerfilResultado(SessionUtil.getFacadeConsultasPerfilesCassiaCore().consultarPerfilbyNombre(Constantes.PERFIL_RESULTADOS_DECOMISO));
			Columns columnsOri = grdResultado.getColumns();
			grdResultado.removeChild(columnsOri);
			Columns columns = new Columns();
			columnsOri.setId("colsResultadoBus");
			columns.setSizable(true);
			columns.setParent(grdResultado);
			PerfilDocumentacion perfilResDec = renderer.getPerfilResultado();
			Collection<AtributosPerfil> atrPerfilResDec = perfilResDec.getAtributos().iterator().next().getHijos();
			if (atrPerfilResDec != null) {
				for (AtributosPerfil atributosPerfil : atrPerfilResDec) {
					Column column = new Column();
					String etiqueta = atributosPerfil.getEtiqueta();
					if (etiqueta == null || etiqueta.trim().length() == 0)
						etiqueta = atributosPerfil.getNombre();
					column.setLabel(etiqueta);
					column.setParent(columns);
				}
			}
			new Column(Labels.getLabel("lbl_adjuntos_decomiso")).setParent(columns);
			new Column(Labels.getLabel("lbl_ver_decomiso")).setParent(columns);
			new Column(Labels.getLabel("lbl_dec_eliminar")).setParent(columns);
			
			Collection<Homologacion> homologaciones = SessionUtil.getFacadeConsultasPerfilesCassiaCore().consultarHomologaciones(ConstantesUtil.getIConstante(Constantes.HOMOLOGACION_TIPO_RESDECOMISO));
			if (homologaciones != null && homologaciones.size() > 0) {
				Homologacion homologacion = homologaciones.iterator().next();
				homologacion = SessionUtil.getFacadeConsultasPerfilesCassiaCore().consultarHomologacion(homologacion);
				renderer.setHomologacion(homologacion);
			}
			grdResultado.setRowRenderer(renderer);
			grdResultado.setModel(mdlResultado);
		}
		((Tab)componente.getRoot().getFellow("tab_resultado")).setSelected(true);
	}

	public void cargarParametrosBusqueda(Grid gridParametros) {
		Rows rows = gridParametros.getRows();
		if (rows != null) {
			gridParametros.removeChild(rows);
		}
		rows = new Rows();
		rows.setParent(gridParametros);
		PerfilDocumentacion perfilBusDec = SessionUtil.getFacadeConsultasPerfilesCassiaCore().consultarPerfilbyNombre(Constantes.PERFIL_BUSQUEDA_DECOMISO);
		Collection<AtributosPerfil> atributos = perfilBusDec.getAtributos();
		if (atributos.size() == 1) {
			AtributosPerfil atributo = atributos.iterator().next();
			Collection<AtributosPerfil> atributosHijos = atributo.getHijos();
			if (atributosHijos != null)
				for (AtributosPerfil atributosPerfilHijo : atributosHijos) {
					Row fila = new Row();
					fila.setAttribute("atributo", atributosPerfilHijo);
					Radiogroup radioGroup = new Radiogroup();
					Radio radioY = new Radio();
					radioY.setId("rdBusAtributo_Y_" + atributosPerfilHijo.getId());
					radioY.setValue("Y");
					radioY.setChecked(true);
					radioY.setLabel(Labels.getLabel("lbl_busqueda_Y"));
					radioY.setParent(radioGroup);
					Radio radioO = new Radio();
					radioO.setId("rdBusAtributo_O_" + atributosPerfilHijo.getId());
					radioO.setValue("O");
					radioO.setLabel(Labels.getLabel("lbl_busqueda_O"));
					radioO.setParent(radioGroup);
					radioGroup.setParent(fila);
					String etiqueta = atributosPerfilHijo.getEtiqueta();
					if (etiqueta == null || etiqueta.trim().length() == 0) {
						etiqueta = atributosPerfilHijo.getNombre();
					}
					org.zkoss.zul.Label label = new org.zkoss.zul.Label(etiqueta);
					label.setParent(fila);
					Component hbox = new Hbox();
					if (XsdTypes.XSD_INTEGER.equals(atributosPerfilHijo.getTipo())) {
						hbox.appendChild(new Label(Labels.getLabel("lbl_valor_entre")));
						Intbox textValorIni = new Intbox();
						textValorIni.setWidth("100px");
						textValorIni.setMaxlength(10);
						textValorIni.setId("txtAtributo_" + atributosPerfilHijo.getId() + "_Ini");
						hbox.appendChild(textValorIni);
						hbox.appendChild(new Label(Labels.getLabel("lbl_valor_entre_y")));
						Intbox textValorFin = new Intbox();
						textValorFin.setWidth("100px");
						textValorFin.setMaxlength(10);
						textValorFin.setId("txtAtributo_" + atributosPerfilHijo.getId() + "_Fin");
						hbox.appendChild(textValorFin);
					} else if (XsdTypes.XSD_DATE.equals(atributosPerfilHijo.getTipo())) {
						hbox.appendChild(new Label(Labels.getLabel("lbl_fecha_entre")));
						Datebox textValorIni = new Datebox();
						textValorIni.setFormat("yyyyMMdd");
						textValorIni.setWidth("100px");
						textValorIni.setReadonly(true);
						textValorIni.setId("txtAtributo_" + atributosPerfilHijo.getId() + "_Ini");
						hbox.appendChild(textValorIni);
						hbox.appendChild(new Label(Labels.getLabel("lbl_fecha_entre_y")));
						Datebox textValorFin = new Datebox();
						textValorFin.setFormat("yyyyMMdd");
						textValorFin.setWidth("100px");
						textValorFin.setMaxlength(10);
						textValorFin.setId("txtAtributo_" + atributosPerfilHijo.getId() + "_Fin");
						hbox.appendChild(textValorFin);
					} else {
						Textbox textBox = new Textbox();
						textBox.setId("txtBusAtributo_" + atributosPerfilHijo.getId());
						textBox.setParent(fila);
						textBox.setWidth("350px");
						hbox.appendChild(textBox);
					}
					hbox.setParent(fila);
					fila.setParent(rows);
				}
		}
	}
	
	public void exportarBusqueda(Grid resultado) {
		String datos = Labels.getLabel("tab_resultados_dec") + "\n";
		datos += ZKUtil.toExcelSinModel(resultado);
		Filedownload filedownload = new Filedownload();
		filedownload.save(datos.getBytes(), "application/vnd.ms-excel", "busqueda-decomisos-" + new SimpleDateFormat("yyyyMMdd").format(new Date()) + ".csv");
	}

}
